package cn.cttic.order.service.impl;

import cn.cttic.base.api.RemoteBaseRecordService;
import cn.cttic.base.api.domain.BaseRecord;
import cn.cttic.base.api.domain.bo.BaseRecordBo;
import cn.cttic.base.api.domain.vo.BaseRecordVo;
import cn.cttic.common.core.utils.BeanCopyUtils;
import cn.cttic.common.core.utils.DateUtils;
import cn.cttic.common.core.utils.MapstructUtils;
import cn.cttic.common.core.utils.StringUtils;
import cn.cttic.common.mybatis.core.page.TableDataInfo;
import cn.cttic.common.mybatis.core.page.PageQuery;
import cn.cttic.common.satoken.utils.LoginHelper;
import cn.cttic.order.api.domain.bo.BaseReconciliationQueryBo;
import cn.cttic.order.util.ExcelToPdfUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import cn.cttic.order.api.domain.bo.BaseReconciliationBo;
import cn.cttic.order.api.domain.vo.BaseReconciliationVo;
import cn.cttic.order.api.domain.BaseReconciliation;
import cn.cttic.order.mapper.BaseReconciliationMapper;
import cn.cttic.order.service.IBaseReconciliationService;

import java.io.*;
import java.net.http.HttpResponse;
import java.util.*;

/**
 * 对账管理Service业务层处理
 *
 * @author Times.Studio
 * @date 2025-01-02
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class BaseReconciliationServiceImpl implements IBaseReconciliationService {

    private final BaseReconciliationMapper baseMapper;

    @DubboReference
    private RemoteBaseRecordService remoteBaseRecordService;

    /**
     * 导出对账单Excel
     *
     * @param id       对账单标识
     * @param response
     */
    @Override
    public void exportReconciliationExcel(String id, HttpServletResponse response) {
        Resource resource = new ClassPathResource("templates/服务对账单.xlsx");
        try {
//            File finalXlsxFile = resource.getFile();
//            FileInputStream inputStream = new FileInputStream(resource.get);
            XSSFWorkbook wbook = new XSSFWorkbook(resource.getInputStream());
            XSSFSheet wsheet = wbook.getSheetAt(0);
            wsheet.getRow(2).getCell(1).setCellValue("添加上文件的路径");

            response.setContentType("application/vnd.ms-excel");
            String downloadFileName = id + "-" + DateUtils.dateTimeNow() + ".xlsx";
            response.setHeader("Content-Disposition", "attachment; filename=\"" + downloadFileName + "\"");

            //添加上文件的路径，组成文件的绝对路径
            OutputStream os = response.getOutputStream();
            wbook.write(os);
            wbook.close();
            os.close();
            //通过流的方式写入到文件中中

//            ExcelToPdfUtil.excelToPdf(file.getPath(),"E:\\demo.pdf",".xlsx");
            //使用完成之后要记得关闭这个流

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 导出对账单PDF
     *
     * @param id       对账单标识
     * @param response
     */
    @Override
    public void exportReconciliationPdf(String id, HttpServletResponse response) {
//        String basePath = getClass().getClassLoader().getResource("").getPath();
//        String fullPath = basePath + "/templates/" + "服务对账单.xlsx";
        Resource resource = new ClassPathResource("templates/服务对账单.xlsx");
        try {
//            File finalXlsxFile = resource.getFile();
//            FileInputStream inputStream = new FileInputStream(resource.get);
            XSSFWorkbook wbook = new XSSFWorkbook(resource.getInputStream());
            XSSFSheet wsheet = wbook.getSheetAt(0);
            wsheet.getRow(2).getCell(1).setCellValue("添加上文件的路径");

            //添加上文件的路径，组成文件的绝对路径
//            wbook.write(response.getOutputStream());
            //通过流的方式写入到文件中中
            InputStream in = null;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            wbook.write(baos);
            in = new ByteArrayInputStream(baos.toByteArray());

            response.setContentType("application/pdf");
            String downloadFileName = id + "-" + DateUtils.dateTimeNow() + ".pdf";
            response.setHeader("Content-Disposition", "attachment; filename=\"" + downloadFileName +  "\"");

            OutputStream os = response.getOutputStream();
            ExcelToPdfUtil.excelToPdf(in, os, ".xlsx");
            os.close();
            //使用完成之后要记得关闭这个流

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询对账管理
     *
     * @param id 主键
     * @return 对账管理
     */
    @Override
    public BaseReconciliationVo queryById(String id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 确认操作
     *
     * @param id 主键
     * @return 对账管理
     */
    @Override
    public BaseReconciliationVo confirm(String id) {
        log.info("[对账单][对账单确认] [开始] {}", id);
        LambdaUpdateWrapper<BaseReconciliation> luw = new LambdaUpdateWrapper<>();
        luw.set(BaseReconciliation::getReconciliationStatus, 1);
        luw.eq(BaseReconciliation::getId, id);
        baseMapper.update(luw);

        // 记录事件
        BaseRecord.BaseRecordBuilder baseRecordBuilder = BaseRecord.BaseRecordBuilder.aBaseRecord();
        BaseRecord baseRecord = baseRecordBuilder.withBusinessId(id)
            .withActionType("对账单")
            .withActionName("对账单（确认）")
            .withActionOperator(LoginHelper.getLoginUser().getNickname() + "(" + LoginHelper.getDeptName() + "-" + LoginHelper.getLoginUser().getPhone() + ")")
            .withActionTime(new Date())
            .withActionResult("确认完成")
            .build();
        BaseRecordVo recordVo = remoteBaseRecordService.addRecord(BeanCopyUtils.copy(baseRecord, BaseRecordBo.class));
        log.info("[对账单][对账单确认] [完成] {}", recordVo);

        return baseMapper.selectVoById(id);
    }

    /**
     * 确认操作
     *
     * @param id 主键
     * @return 对账管理
     */
    @Override
    public List<BaseReconciliationVo> batchConfirm(List<String> ids) {

        for (String id : ids) {
            log.info("[对账单][对账单确认] [开始] {}", id);
            LambdaUpdateWrapper<BaseReconciliation> luw = new LambdaUpdateWrapper<>();
            luw.set(BaseReconciliation::getReconciliationStatus, 1);
            luw.eq(BaseReconciliation::getId, id);
            baseMapper.update(luw);

            // 记录事件
            BaseRecord.BaseRecordBuilder baseRecordBuilder = BaseRecord.BaseRecordBuilder.aBaseRecord();
            BaseRecord baseRecord = baseRecordBuilder.withBusinessId(id)
                .withActionType("对账单")
                .withActionName("对账单（确认）")
                .withActionOperator(LoginHelper.getLoginUser().getNickname() + "(" + LoginHelper.getDeptName() + "-" + LoginHelper.getLoginUser().getPhone() + ")")
                .withActionTime(new Date())
                .withActionResult("确认完成")
                .build();
            BaseRecordVo recordVo = remoteBaseRecordService.addRecord(BeanCopyUtils.copy(baseRecord, BaseRecordBo.class));
            log.info("[对账单][对账单确认] [完成] {}", recordVo);
        }

        return baseMapper.selectVoBatchIds(ids);
    }

    /**
     * 确认操作
     *
     * @param id                   主键
     * @param reconciliationStatus
     * @param reconciliationReason
     * @param writeOffApprovalNo
     * @param writeOffProof
     * @return 对账管理
     */
    @Override
    public BaseReconciliationVo audit(String id, Integer reconciliationStatus, String reconciliationReason, String writeOffApprovalNo, String writeOffProof) {
        log.info("[对账单][对账单审核] [开始] {}", id);
        LambdaUpdateWrapper<BaseReconciliation> luw = new LambdaUpdateWrapper<>();
        // 设置核销状态
        if (reconciliationStatus == 2) {
            luw.set(BaseReconciliation::getReconciliationStatus, 2);
            luw.set(BaseReconciliation::getWriteOffStatus, 1);
        } else if (reconciliationStatus == 3) {
            luw.set(BaseReconciliation::getReconciliationStatus, 3);
        }
        // 设置核销意见
        luw.set(BaseReconciliation::getReconciliationReason, reconciliationReason);
        luw.set(BaseReconciliation::getWriteOffReason, reconciliationReason);
        // 核销审批单号
        luw.set(BaseReconciliation::getWriteOffApprovalNo, writeOffApprovalNo);
        // 核销证明
        luw.set(StrUtil.isNotEmpty(writeOffProof), BaseReconciliation::getWriteOffProof, writeOffProof);
        // 更新条件
        luw.eq(BaseReconciliation::getId, id);
        baseMapper.update(luw);

        // 记录事件
        BaseRecord.BaseRecordBuilder baseRecordBuilder = BaseRecord.BaseRecordBuilder.aBaseRecord();
        BaseRecord baseRecord = baseRecordBuilder.withBusinessId(id)
            .withActionType("对账单")
            .withActionName("对账单（审核）")
            .withActionOperator(LoginHelper.getLoginUser().getNickname() + "(" + LoginHelper.getDeptName() + "-" + LoginHelper.getLoginUser().getPhone() + ")")
            .withActionTime(new Date())
            .withActionResult(reconciliationStatus == 1 ? "审核通过" : "审核未通过")
            .withActionResultContent(reconciliationReason)
            .build();
        BaseRecordVo recordVo = remoteBaseRecordService.addRecord(BeanCopyUtils.copy(baseRecord, BaseRecordBo.class));
        log.info("[对账单][对账单审核] [完成] {}", recordVo);

        return baseMapper.selectVoById(id);
    }

    /**
     * 确认操作
     *
     * @param id          主键
     * @param receiptInfo
     * @return 对账管理
     */
    @Override
    public BaseReconciliationVo ticket(String id, String receiptInfo) {
        log.info("[对账单][对账单开票] [开始] {}", id);

        LambdaUpdateWrapper<BaseReconciliation> luw = new LambdaUpdateWrapper<>();
        luw.set(BaseReconciliation::getReceiptInfo, receiptInfo);
        luw.set(BaseReconciliation::getWriteOffStatus, 2);
        // 更新条件
        luw.eq(BaseReconciliation::getId, id);
        baseMapper.update(luw);

        // 记录事件
        BaseRecord.BaseRecordBuilder baseRecordBuilder = BaseRecord.BaseRecordBuilder.aBaseRecord();
        BaseRecord baseRecord = baseRecordBuilder.withBusinessId(id)
            .withActionType("对账单")
            .withActionName("对账单（开票）")
            .withActionOperator(LoginHelper.getLoginUser().getNickname() + "(" + LoginHelper.getDeptName() + "-" + LoginHelper.getLoginUser().getPhone() + ")")
            .withActionTime(new Date())
            .withActionResult("开票完成")
            .build();
        BaseRecordVo recordVo = remoteBaseRecordService.addRecord(BeanCopyUtils.copy(baseRecord, BaseRecordBo.class));
        log.info("[对账单][对账单开票] [完成] {}", recordVo);

        return baseMapper.selectVoById(id);
    }

    /**
     * 确认操作
     *
     * @param id        主键
     * @param paidProof
     * @return 对账管理
     */
    @Override
    public BaseReconciliationVo accomplish(String id, String paidProof) {
        log.info("[对账单][对账单开票] [完成] {}", id);

        LambdaUpdateWrapper<BaseReconciliation> luw = new LambdaUpdateWrapper<>();
        luw.set(BaseReconciliation::getPaidProof, paidProof);
        luw.set(BaseReconciliation::getWriteOffStatus, 3);
        // 更新条件
        luw.eq(BaseReconciliation::getId, id);
        baseMapper.update(luw);

        // 记录事件
        BaseRecord.BaseRecordBuilder baseRecordBuilder = BaseRecord.BaseRecordBuilder.aBaseRecord();
        BaseRecord baseRecord = baseRecordBuilder.withBusinessId(id)
            .withActionType("对账单")
            .withActionName("对账单（付款）")
            .withActionOperator(LoginHelper.getLoginUser().getNickname() + "(" + LoginHelper.getDeptName() + "-" + LoginHelper.getLoginUser().getPhone() + ")")
            .withActionTime(new Date())
            .withActionResult("付款完成")
            .build();
        BaseRecordVo recordVo = remoteBaseRecordService.addRecord(BeanCopyUtils.copy(baseRecord, BaseRecordBo.class));
        log.info("[对账单][对账单开票] [完成] {}", recordVo);

        return baseMapper.selectVoById(id);
    }

    /**
     * 查询对账单记录
     *
     * @param bo
     * @return
     */
    @Override
    public List<BaseRecordVo> queryRecordList(BaseReconciliationQueryBo bo) {
        return remoteBaseRecordService.getRecordList(bo.getId());
    }

    /**
     * 分页查询对账管理列表
     *
     * @param bo 查询条件
     * @return 对账管理分页列表
     */
    @Override
    public TableDataInfo<BaseReconciliationVo> queryReconciliationPageList(BaseReconciliationQueryBo bo) {
        QueryWrapper<BaseReconciliation> lqw = buildReconciliationQueryWrapper(bo);
        Page<BaseReconciliationVo> result = baseMapper.getPagedReconciliationList(bo.build(), lqw);
        return TableDataInfo.build(result);
    }

    private QueryWrapper<BaseReconciliation> buildReconciliationQueryWrapper(BaseReconciliationQueryBo bo) {
        QueryWrapper<BaseReconciliation> lqw = new QueryWrapper<>();
        lqw.eq(StringUtils.isNotBlank(bo.getId()), "br.id", bo.getId());
        lqw.eq(StringUtils.isNotBlank(bo.getCompanyId()), "br.company_id", bo.getCompanyId());
        lqw.ge(bo.getCreateTimeBegin() != null, "br.create_time", bo.getCreateTimeBegin());
        lqw.le(bo.getCreateTimeEnd() != null, "br.create_time", bo.getCreateTimeEnd());
        lqw.eq(StringUtils.isNotBlank(bo.getImei()), "brd.terminal_imei", bo.getImei());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderType()), "br.order_type", bo.getOrderType());
        if (bo.getReconciliationStatus() != null) {
            lqw.eq("br.reconciliation_status", bo.getReconciliationStatus());
        } else {
            lqw.ne("br.reconciliation_status", 1);
        }
        lqw.eq(bo.getWriteOffStatus() != null, "br.write_off_status", bo.getWriteOffStatus());
        return lqw;
    }

    /**
     * 分页查询对账管理列表
     *
     * @param bo 查询条件
     * @return 对账管理分页列表
     */
    @Override
    public TableDataInfo<BaseReconciliationVo> queryWriteOffPageList(BaseReconciliationQueryBo bo) {
        QueryWrapper<BaseReconciliation> lqw = buildWriteOffQueryWrapper(bo);
        Page<BaseReconciliationVo> result = baseMapper.getPagedReconciliationList(bo.build(), lqw);
        return TableDataInfo.build(result);
    }

    private QueryWrapper<BaseReconciliation> buildWriteOffQueryWrapper(BaseReconciliationQueryBo bo) {
        QueryWrapper<BaseReconciliation> lqw = new QueryWrapper<>();
        lqw.eq(StringUtils.isNotBlank(bo.getId()), "br.id", bo.getId());
        lqw.eq(StringUtils.isNotBlank(bo.getCompanyId()), "br.company_id", bo.getCompanyId());
        lqw.ge(bo.getCreateTimeBegin() != null, "br.create_time", bo.getCreateTimeBegin());
        lqw.le(bo.getCreateTimeEnd() != null, "br.create_time", bo.getCreateTimeEnd());
        lqw.eq(StringUtils.isNotBlank(bo.getImei()), "brd.terminal_imei", bo.getImei());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderType()), "br.order_type", bo.getOrderType());
//        if (bo.getReconciliationStatus() != null) {
//            lqw.eq("br.reconciliation_status", bo.getReconciliationStatus());
//        } else {
        lqw.in("br.reconciliation_status", Arrays.asList(1, 2));
//        }
        lqw.eq(bo.getWriteOffStatus() != null, "br.write_off_status", bo.getWriteOffStatus());
        return lqw;
    }

    /**
     * 分页查询对账管理列表
     * 7    * @param bo        查询条件
     *
     * @param pageQuery 分页参数
     * @return 对账管理分页列表
     */
    @Override
    public TableDataInfo<BaseReconciliationVo> queryPageList(BaseReconciliationBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<BaseReconciliation> lqw = buildQueryWrapper(bo);
        Page<BaseReconciliationVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的对账管理列表
     *
     * @param bo 查询条件
     * @return 对账管理列表
     */
    @Override
    public List<BaseReconciliationVo> queryList(BaseReconciliationBo bo) {
        LambdaQueryWrapper<BaseReconciliation> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<BaseReconciliation> buildQueryWrapper(BaseReconciliationBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<BaseReconciliation> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getCompanyId()), BaseReconciliation::getCompanyId, bo.getCompanyId());
        lqw.eq(bo.getPeriodBeginDate() != null, BaseReconciliation::getPeriodBeginDate, bo.getPeriodBeginDate());
        lqw.eq(bo.getPeriodEndDate() != null, BaseReconciliation::getPeriodEndDate, bo.getPeriodEndDate());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderType()), BaseReconciliation::getOrderType, bo.getOrderType());
        lqw.eq(bo.getOrderCount() != null, BaseReconciliation::getOrderCount, bo.getOrderCount());
        lqw.eq(bo.getReconciliationStatus() != null, BaseReconciliation::getReconciliationStatus, bo.getReconciliationStatus());
        lqw.eq(bo.getStartingWriteOff() != null, BaseReconciliation::getStartingWriteOff, bo.getStartingWriteOff());
        lqw.eq(bo.getWriteOffStatus() != null, BaseReconciliation::getWriteOffStatus, bo.getWriteOffStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getWriteOffReason()), BaseReconciliation::getWriteOffReason, bo.getWriteOffReason());
        lqw.eq(StringUtils.isNotBlank(bo.getWriteOffApprovalNo()), BaseReconciliation::getWriteOffApprovalNo, bo.getWriteOffApprovalNo());
        lqw.eq(StringUtils.isNotBlank(bo.getWriteOffProof()), BaseReconciliation::getWriteOffProof, bo.getWriteOffProof());
        lqw.eq(StringUtils.isNotBlank(bo.getHasReceipt()), BaseReconciliation::getHasReceipt, bo.getHasReceipt());
        lqw.eq(StringUtils.isNotBlank(bo.getReceiptInfo()), BaseReconciliation::getReceiptInfo, bo.getReceiptInfo());
        lqw.eq(StringUtils.isNotBlank(bo.getPaidProof()), BaseReconciliation::getPaidProof, bo.getPaidProof());
        lqw.eq(bo.getCreateTime() != null, BaseReconciliation::getCreateTime, bo.getCreateTime());
        return lqw;
    }

    /**
     * 新增对账管理
     *
     * @param bo 对账管理
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(BaseReconciliationBo bo) {
        BaseReconciliation add = MapstructUtils.convert(bo, BaseReconciliation.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改对账管理
     *
     * @param bo 对账管理
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(BaseReconciliationBo bo) {
        BaseReconciliation update = MapstructUtils.convert(bo, BaseReconciliation.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(BaseReconciliation entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除对账管理信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
}
